#include "es_C24.h"
//#include <cstdio.h>
//#include <cstdlib.h>

//#define DEBUG

#ifdef DEBUG
#define debug(msg) print(msg);
#else
#define debug(msg)
#endif

extern void print(char *);







NodeInfo C24_info;
u8 C_24wait_for_ACK = 0;
u8 C24_tx_addr[5];
u8 C24_rx_addr[5];

u8 C24_pow_speed;

/**************************公共函数*****************************/
commPackage CommCreatePacket(u8 *data, int len, u8 *myaddr, AckType ack, SendAddr addr, u8 flag)
{
    commPackage cp;
    u8 i = 0;

    //init flag setting
    cp.flag = flag;
    cp.flag &= 0x3f;

    //ack
    if (ack == ACK)
    {
	cp.flag |= 0x40;
    }
    if (addr == SEND_ADDR)
    {
	cp.flag |= 0x80;

	if (len > 26)
	    return cp;
	for (i = 0; i < 5; i++)
	{
	    cp.package[i + 1] = myaddr[i];
	}
	for (i = 6; i < len + 6; i++)
	{
	    cp.package[i] = data[i - 6];
	}
	cp.length = len + 6;
    }
    else
    {
	if (len > 31)
	    return cp;
	for (i = 1; i < len + 1; i++)
	{
	    cp.package[i] = data[i - 1];
	}
	cp.length = len + 1;
    }
    cp.package[0] = cp.flag;

    return cp;
}

void C24Init()
{
    NRFInit(NRF24_H_250k);

    C24IRQ();
    C24IRQ();

    debug("\r\n\r\n\r\n2.4 comm layer init done!!!\r\n");
}

//这函数应该被irq24 call， 然后它会通过decode() call new24DataEventHandler
void C24IRQ(void)
{
    u8 len;
    u8 rxData[32];
    commPackage package;

    int i;
    //if not in middle of TX
    if (C_24wait_for_ACK == false)
    {

	debug("irq24 called\r\n");

	if (NRFrxData(C24_info.nodeAddr, rxData, &len) == RX_DR)
	{
	    //construct package
	    commPackage *pack = &package; //malloc(sizeof(commPackage));

	    setBytes(rxData, len, pack);

	    decode(pack);

	    //ouput data to serial port
	    //			if (true) {
	    //
	    //#ifdef __ES_DEBUG__
	    //				char str[100];
	    //
	    //				sprintf(str, "sender: %d, %d, %d, %d, %d\r\n", rxData[1], rxData[2], rxData[3], rxData[4], rxData[5]);
	    //				debug(str);
	    //
	    //				sprintf(str, "flag: %d length: %d Data:", rxData[0], len);
	    //				debug(str);
	    //
	    //
	    //
	    //				for (i = 6; i < len; i++)
	    //				{
	    //					sprintf(str, "%d ", rxData[i]);
	    //					debug(str);
	    //				}
	    //				debug("\r\n");
	    //#endif
	    //
	    //
	    //			}
	}
    }
    else //if it's waiting ACK
    {
	debug("ack\n");
	NRFflushTx();
	C_24wait_for_ACK = false;
	NRFrx_mode();
    }
    //		return 0;
}

void C24Tx(u8 *addr, commPackage *p)
{
    u8 *data;

    u8 len;

    len = getBytes(p, &data);
    NRFtxData(addr, data, len);
}

/******************************需要修改的函数******************************/
void init_rcc()
{
}
void init_gpio()
{
    //CE
    GPIO_Init(GPIOD, GPIO_PIN_2, GPIO_MODE_OUT_PP_HIGH_FAST);

    //CSN
    GPIO_Init(GPIOA, GPIO_PIN_3, GPIO_MODE_OUT_PP_HIGH_FAST);

    //IRQ
    GPIO_Init(GPIOD, GPIO_PIN_3, GPIO_MODE_IN_PU_IT);

    NRF_CSN_HIGH();
}
void IRQ_config()
{
    EXTI_SetExtIntSensitivity(EXTI_PORT_GPIOD, EXTI_SENSITIVITY_FALL_ONLY);
    
}

/**************************私有函数*****************************/

/*
* power_speed：功率速率，见顶部define
*/
void NRFInit(u8 power_speed)
{
    C24_pow_speed = power_speed;

    init_rcc();
    init_gpio();

    IRQ_config();

    C_24wait_for_ACK = false;

    NRFrx_mode();
}
u8 NRF_Check(void)
{
    u8 buf[5] = {0xC2, 0xC2, 0xC2, 0xC2, 0xC2};
    u8 buf1[5];
    u8 i;

    //write and then read, check for the same data
    writeBuffer(NRF_WRITE_REG + TX_ADDR, buf, 5);

    readBuffer(TX_ADDR, buf1, 5);

    for (i = 0; i < 5; i++)
    {
	if (buf1[i] != 0xC2)
	    break;
    }

    if (i == 5)
	return 1; //nrf-spi works
    else
	return 0; //not working
}

u8 NRFtxData(u8 *addr, u8 *txBuffer, u8 len)
{
    int i;

    //如果正在等ack， 退出， 丢掉当前发送包，返回错误
    if (C_24wait_for_ACK)
	return 1;

    //set address0
    for (i = 0; i < 5; i++)
    {
	C24_tx_addr[i] = addr[i];
	C24_rx_addr[i] = addr[i];
    }
    tx_mode();
    return tx(txBuffer, len);
}

u8 NRFrxData(u8 *addr, u8 *rxBuffer, u8 *len)
{
    //set address
    int i;
    for (i = 0; i < 5; i++)
    {
	C24_rx_addr[i] = addr[i];
    }
    NRFrx_mode();
    return rx(rxBuffer, len);
}

u8 readStat()
{
    u8 stat;

    stat = readReg(STATUS);

    return stat;
}
void NRFflushTx()
{
    writeReg(NRF_WRITE_REG + STATUS, readStat());

    writeReg(FLUSH_TX, NOP);
}
void flushRx()
{
    writeReg(FLUSH_RX, NOP);
}

void NRFrx_mode()
{
    NRF_CE_LOW();
    //spi.WriteReg()
    writeBuffer(NRF_WRITE_REG + RX_ADDR_P0, C24_rx_addr, RX_ADR_WIDTH); //????RX??????????????·

    writeReg(NRF_WRITE_REG + EN_AA, 0x01); //??????????¨????0????×??????????????

    writeReg(NRF_WRITE_REG + EN_RXADDR, 0x01); //??????????¨????0??????????????????·

    writeReg(NRF_WRITE_REG + RF_CH, CHANAL); //??è????RF??¨????????????

    writeReg(NRF_WRITE_REG + RX_PW_P0, 3); //??????????¨????0??????????§??????????í????

    writeReg(NRF_WRITE_REG + RF_SETUP, C24_pow_speed); //速率功率

    writeReg(NRF_WRITE_REG + CONFIG, 0x0f); //??????????ù±????¤×÷????????????????????;PWR_UP,EN_CRC,16BIT_CRC,????????????????

    //enable ack payload and dynamic payload
    writeReg(NRF_WRITE_REG + FEATURE, 0x06);

    //enable dynamic payload length
    writeReg(NRF_WRITE_REG + DYNPD, 0x01);

    NRF_CE_HIGH();
}

u8 rx(u8 *buff, u8 *len)
{
    u8 stat;
    //
    //  	//NRF_CE_HIGH();
    //		//wait for IRQ
    //		//while(NRF_Read_IRQ()!=0);
    //
    NRF_CE_LOW();
    //
    //read status reg
    stat = readReg(STATUS);

    //clear IRQ
    writeReg(NRF_WRITE_REG + STATUS, stat);

    //read data len
    *len = readReg(R_RX_PL_WID);
    //
    //		//data received
    if (stat & RX_DR)
    {
	readBuffer(RD_RX_PLOAD, buff, *len);

	writeReg(FLUSH_RX, NOP);
	//
	return RX_DR;
    } // nodata
    return ERROR;
}
u8 tx(u8 *buff, u8 len)
{
    /*ce??????????????????????????ú????????1*/
    NRF_CE_LOW();

    /*????????????????TX BUF ×????ó 32????×??????*/
    writeBuffer(WR_TX_PLOAD, buff, len);

    //chip enable set to HIGH
    NRF_CE_HIGH();

    //lock irq
    return (C_24wait_for_ACK = true);
}

void tx_mode()
{
    //		int i;
    NRF_CE_LOW();

    writeBuffer(NRF_WRITE_REG + TX_ADDR, C24_tx_addr, TX_ADR_WIDTH); //????TX??????????????·

    writeBuffer(NRF_WRITE_REG + RX_ADDR_P0, C24_rx_addr, RX_ADR_WIDTH); //??è????TX??????????????·,??÷????????????????????ACK

    writeReg(NRF_WRITE_REG + EN_AA, 0x01); //??????????¨????0????×??????????????

    writeReg(NRF_WRITE_REG + EN_RXADDR, 0x01); //??????????¨????0??????????????????·

    writeReg(NRF_WRITE_REG + SETUP_RETR, 0x1a); //??è????×??????????·????????????±????:500us + 86us;×????ó×??????????·??????????:10????

    writeReg(NRF_WRITE_REG + RF_CH, CHANAL); //??è????RF??¨????????CHANAL

    writeReg(NRF_WRITE_REG + RF_SETUP, C24_pow_speed); //速率功率

    writeReg(NRF_WRITE_REG + CONFIG, 0x0e); //??????????ù±????¤×÷????????????????????;PWR_UP,EN_CRC,16BIT_CRC,·??????????????,??????????ù????????????

    /*CE????????????????????·??????????????*/
    NRF_CE_HIGH();

    //for( i=0;i<10000;i++);
}

u8 readReg(u8 reg)
{
    u8 result;

    //set nrf pins to enable chip and communication
    NRF_CE_LOW();
    NRF_CSN_LOW();

    //read
    result = SpiReadReg(reg);

    //disable communication
    NRF_CSN_HIGH();
    NRF_CE_HIGH();
    return result;
}
u8 writeReg(u8 reg, u8 data)
{
    u8 stat;

    NRF_CE_LOW();
    NRF_CSN_LOW();

    stat = SpiWriteReg(reg, data);

    NRF_CSN_HIGH();
    NRF_CE_HIGH();
    return stat;
}

u8 writeBuffer(u8 reg, u8 *buf, u8 len)
{
    u8 stat;
    //enable chip
    NRF_CE_LOW();
    //enable spi communication
    NRF_CSN_LOW();
    //write from spi bus
    stat = SpiWriteBuf(reg, buf, len);
    //disable spi
    NRF_CSN_HIGH();
    NRF_CE_HIGH();
    return stat;
}

u8 readBuffer(u8 reg, u8 *buf, u8 len)
{
    u8 stat;
    //enable chip
    NRF_CE_LOW();
    //enable spi communication
    NRF_CSN_LOW();
    //read from spi bus
    stat = SpiReadBuf(reg, buf, len);
    //disable spi
    NRF_CSN_HIGH();

    NRF_CE_HIGH();
    return stat;
}

u8 getBytes(commPackage *p, u8 **data)
{
    (*data) = p->package;
    return p->length;
}

void setBytes(u8 *data, u8 len, commPackage *cp)
{
    int i;
    for (i = 0; i < len; i++)
    {
	cp->package[i] = data[i];
    }
    cp->flag = cp->package[0];
    cp->length = len;
}

void decode(commPackage *p)
{
    //commPackage* pack = p;
    u8 *data;
    u8 len;
    int i;
    u8 senderAddr[5];
    u8 decodedData[26];
    u8 flag;

    char str[100];

    //extract infomation from package
    len = getBytes(p, &data);
#ifdef __ES_DEBUG__

    sprintf(str, "flag: %d\r\n", p->package[0]);
    debug(str);
#endif
    if (len != 0)
    {
	//if requires ack
	//send ack

	//if the package contains sender's address
	if ((data[0] & 0x80) > 0 && len > 6)
	{
	    debug("decoder\r\n");
	    //get sender

	    for (i = 0; i < 5; i++)
	    {
		senderAddr[i] = data[i + 1];
	    }
	    //get data
	    for (i = 6; i < len; i++)
	    {
		decodedData[i - 6] = data[i];
	    }

	    //get flag
	    flag = data[0];

	    new24DataEventHandler(flag, senderAddr, decodedData, len - 6);
	}
    }
}

